package com.crm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.crm.entity.*;
import com.crm.mapper.*;
import com.crm.vo.ClientsVO;
import com.crm.context.BaseContext;
import com.crm.dto.ContractDto;
import com.crm.dto.CountDto.ClientsDto;
import com.crm.result.PageResult;
import com.crm.service.ContractService;
import com.crm.utils.StringUtils;
import com.crm.vo.SaleVo;
import com.crm.vo.SeriesVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


import static com.crm.entity.Contract.CONTRACT_STATUS_WAITING;

@Service
@RequiredArgsConstructor
@Slf4j
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {

    private final ContractMapper contractMapper;
    private final DeptMapper deptMapper;
    private final UserMapper userMapper;
    private final ActivityMapper activityMapper;
    private final CourseMapper courseMapper;
    private final BusinessMapper businessMapper;
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public PageResult pageContract(ContractDto contractDto) {
        Page<Contract> page = new Page<>(contractDto.getPageNum(), contractDto.getPageSize());

        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<Contract>();
        wrapper.eq(StringUtils.hasText(contractDto.getContractNo()),Contract::getContractNo,contractDto.getContractNo());
        wrapper.like(StringUtils.hasText(contractDto.getName()),Contract::getName,contractDto.getName());
        wrapper.eq(StringUtils.hasText(contractDto.getPhone()),Contract::getPhone,contractDto.getPhone());
        wrapper.eq(contractDto.getCourseId()!=null,Contract::getCourseId,contractDto.getCourseId());
        wrapper.eq(StringUtils.hasText(contractDto.getSubject()),Contract::getSubject,contractDto.getSubject());
        wrapper.eq(StringUtils.hasText(contractDto.getContractNo()),Contract::getContractNo,contractDto.getContractNo());

        wrapper.between(StringUtils.hasText(contractDto.getCreateTime()),Contract::getCreateTime,contractDto.getParams().get("beginCreateTime"),contractDto.getParams().get("endCreateTime"));

        Page<Contract> contractPage = contractMapper.selectPage(page, wrapper);

        return new PageResult(contractPage.getTotal(),contractPage.getRecords());
    }

    @Override
    public void add(ContractDto contractDto) {
        Contract contract = new Contract();
        BeanUtils.copyProperties(contractDto,contract);
        contract.setCourseId(contractDto.getCourseId());
        //创建人
        Long userId = BaseContext.getCurrentId();
        User user = userMapper.selectById(userId);
        contract.setCreateBy(user.getUserName());
        //部门ID
        contract.setDeptId(user.getDeptId());
        //创建时间
        contract.setCreateTime(LocalDateTime.now().toString());
        //活动id，课程折扣类型
        contract.setActivityId(contractDto.getActivityId());

        LambdaQueryWrapper<Activity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Activity::getId,contractDto.getActivityId());
        Activity activity = activityMapper.selectOne(wrapper);
        if (activity != null) {
            contract.setDiscountType(activity.getType());
        } else {
            // 可设置默认值、抛出自定义异常、或记录日志
            contract.setDiscountType(null); // 示例：设为空或默认值
            // log.warn("Activity not found for id: {}", contractDto.getActivityId());
        }
        //课程价格，
        Course course = courseMapper.selectById(contractDto.getCourseId());
        contract.setCoursePrice(course.getPrice());

        //合同金额
        Double order =0.0;
        if("1".equals(activity.getType())){//课程折扣
            order = course.getPrice() * Double.parseDouble(activity.getDiscount());
            contract.setOrder(order);
        }else if ("2".equals(activity.getType())){//课程代金券
            order = course.getPrice() - activity.getVouchers();
            contract.setOrder(order);
        }else{
            throw new RuntimeException("未知金额情况");
        }

        //合同状态
        contract.setStatus(CONTRACT_STATUS_WAITING);
        contract.setBusinessId(66666l);
        contract.setFinishTime(LocalDateTime.now().toString());

        contractMapper.insert(contract);
    }

    @Override
    public Contract selectContractById(Long id) {
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Contract::getId,id);

        Contract contract = contractMapper.selectOne(wrapper);
        return contract;
    }
    /**
     * 客户列表分页查询
     * @param clientsDto
     * @return
     */
    @Override
    public PageResult ClientsPage(ClientsDto clientsDto) {
        Page<Contract> page = new Page<>(clientsDto.getPageNum(), clientsDto.getPageSize());
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StringUtils.isNotEmpty(clientsDto.getChannel()), Contract::getChannel,clientsDto.getChannel());
        wrapper.eq(StringUtils.isNotEmpty(clientsDto.getDeptId()), Contract::getDeptId,clientsDto.getDeptId());
        wrapper.eq(StringUtils.isNotEmpty(clientsDto.getCreateBy()), Contract::getCreateBy,clientsDto.getCreateBy());
        contractMapper.selectPage(page, wrapper);
        return new PageResult(page.getTotal(),page.getRecords());
    }

    /**
     * 销售统计
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public ClientsVO saleCount(String beginCreateTime, String endCreateTime) {
        LocalDate begin = LocalDate.parse(beginCreateTime, DATE_FORMATTER);
        LocalDate end = LocalDate.parse(endCreateTime, DATE_FORMATTER);
        ClientsVO clientsVO = new ClientsVO();

        List<Contract> contracts = contractMapper.selectTime(begin, end);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //拿到contracts集合的所以创建时间修改成localdate形式放到集合中
        List<LocalDate> localDates = contracts.stream()
                .map(contract -> LocalDate.parse(contract.getCreateTime(),formatter))
                .collect(Collectors.toList());
        //把localdate集合转成字符串
        clientsVO.setXAxis(localDates);
        List<SeriesVO> seriesList = new ArrayList<>();
        SeriesVO seriesVO = new SeriesVO();
        seriesVO.setName("销售数量");
        List<Integer> saleAmounts =  new ArrayList<>();
        for (LocalDate localDate : localDates) {
            //统计金额
            Long count = contractMapper.selectCountSale(begin,localDate);
            if (count != null) {
                saleAmounts.add(count.intValue());
            }
        }
        seriesVO.setData(saleAmounts);
        seriesList.add(seriesVO);
        clientsVO.setSeries(seriesList);
        return clientsVO;
    }

    /**
     * 销售列表分页查询
     * @param contractDto
     * @return
     */
    @Override
    public PageResult SaleList(String beginCreateTime,String endCreateTime,ContractDto contractDto) {
        //  查询指定时间段内的合同数据
        LocalDate begin = LocalDate.parse(beginCreateTime, DATE_FORMATTER);
        LocalDate end = LocalDate.parse(endCreateTime, DATE_FORMATTER);
        Page<Contract> page = new Page<>();
        List<SaleVo> contracts = contractMapper.selectSaleList(page,begin,end);
        return new PageResult(page.getTotal(),contracts);
    }

    /**
     * 统计客户图表
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public ClientsVO queryByDateRange(String beginCreateTime, String endCreateTime) {
        LocalDate begin = LocalDate.parse(beginCreateTime, DATE_FORMATTER);
        LocalDate end = LocalDate.parse(endCreateTime, DATE_FORMATTER);
        ClientsVO clientsVO = new ClientsVO();

        List<Contract> contracts = contractMapper.selectDateTime(begin, end);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        //拿到contracts集合的所以创建时间修改成localdate形式放到集合中
        List<LocalDate> localDates = contracts.stream()
                .map(contract -> LocalDate.parse(contract.getCreateTime(),formatter))
                .collect(Collectors.toList());
        //把localdate集合转成字符串
        clientsVO.setXAxis(localDates);
        //新增客户数
        List<Integer> dataList = new ArrayList<>();
        //客户总数
        List<Integer> allDataList = new ArrayList<>();
        //拿到每天的总数
        for (LocalDate localDate : localDates) {
            Long count = contractMapper.selectCount(Wrappers.<Contract>lambdaQuery().like(Contract::getCreateTime, localDate));
            if (count != null && count > 0){
                dataList.add(count.intValue());
            }
            //查询客户总数
            Long totalCount = contractMapper.selectCount(Wrappers.<Contract>lambdaQuery().between(Contract::getCreateTime,begin,localDate));
            allDataList.add(totalCount.intValue());
        }
        SeriesVO seriesVO = new SeriesVO();
        seriesVO.setName("新增客户数");
        seriesVO.setData(dataList);
        SeriesVO allSeriesVO = new SeriesVO();
        allSeriesVO.setName("客户总数");
        allSeriesVO.setData(allDataList);
        List<SeriesVO> series = new ArrayList<>();
        series.add(seriesVO);
        series.add(allSeriesVO);
        clientsVO.setSeries(series);
        return clientsVO;
    }

    /**
     * 商机转合同
     * @param id
     */
    @Override
    public void changeContract(Long id) {
        log.info("商机转合同",id);
        businessMapper.updateContractType(id);
        Contract contract = new Contract();
        Business business = businessMapper.selectById(id);
        contract.setBusinessId(id);
        contract.setCreateTime(String.valueOf(business.getCreateTime()));
        contract.setName(business.getName());
        contract.setChannel(String.valueOf(business.getChannel()));
        contract.setPhone(business.getPhone());
        contract.setStatus(String.valueOf(business.getStatus()));
        contractMapper.insert(contract);
    }

    /**
     * 构建图表序列
     * @param dataMap
     * @param datelist
     * @return
     */
    private List<SeriesVO> buildSeriesList(Map<String, Map<String, Integer>> dataMap, List<String> datelist) {
        List<SeriesVO> seriesList = new ArrayList<>();
        //新增客户序列
        SeriesVO seriesVO = new SeriesVO();
        seriesVO.setName("新增客户数");
        List<Integer> newCustomerData = new ArrayList<>();
        //客户总数序列
        SeriesVO totalCustomerVO = new SeriesVO();
        totalCustomerVO.setName("客户总数");
        List<Integer> totalCustomerData = new ArrayList<>();
        //遍历日期列表，填充数据
        for (String date : datelist) {
            Map<String,  Integer> dailyData=dataMap.getOrDefault(date,new HashMap<>());
            newCustomerData.add(dailyData.getOrDefault("newCustomerCount",0));
            totalCustomerData.add(dailyData.getOrDefault("totalCustomerCount",0));
        }
        seriesVO.setData(newCustomerData);
        totalCustomerVO.setData(totalCustomerData);
        seriesList.add(seriesVO);
        seriesList.add(totalCustomerVO);
        return seriesList;
    }

    /**
     * 从数据库获取统计数据
     * @param begin
     * @param end
     * @return
     */
    private List<Contract> fetchStatisticsFromDB(LocalDate begin, LocalDate end) {
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("create_time",
                              begin.format(DATE_FORMATTER),
                              end.format(DATE_FORMATTER));
        return contractMapper.selectList(queryWrapper);
    }

    /**
     * 生成日期范围内所有日期字符串列表
     * @param begin
     * @param end
     * @return
     */
    private List<String> generateDateList(LocalDate begin, LocalDate end) {
        List<String> dateList = new ArrayList<>();
        LocalDate currentDate = begin;
        while (!currentDate.isAfter(end)) {
            dateList.add(currentDate.format(DATE_FORMATTER));
            begin = begin.plusDays(1);
        }
        return dateList;
    }
    /**
     * 处理统计数据
     * @param contractsList
     * @param datelist
     * @return
     */
    private Map<String, Map<String, Integer>> processStatistics(List<Contract> contractsList, List<String> datelist) {
        //初始化数据映射
        Map<String, Map<String, Integer>> dataMap = new HashMap<>();
        for (String date : datelist) {
            dataMap.put(date, new HashMap<>());
        }
        //填充数据
        for (Contract contract : contractsList) {
            //先将字符串解析为 LocalDate，再格式化为字符串
            LocalDate localDate = LocalDate.parse(contract.getCreateTime(), DATE_FORMATTER);
            String date = localDate.format(DATE_FORMATTER);
            Map<String, Integer> channelMap = dataMap.computeIfAbsent(date, k -> new HashMap<>());
            channelMap.put("newCustomer",contract.getNewCustomerCount());
            channelMap.put("totalCustomer",contract.getTotalCustomerCount());
        }
        return dataMap;
    }

}
